#include "xVertexDeclaration.h"
#include "xLogManager.h"


namespace XE
{


	xVertexDeclaration::xVertexDeclaration()
	{

	}
	xVertexDeclaration::~xVertexDeclaration()
	{

	}

	bool xVertexDeclaration::AddVertexElement( WORD Stream,WORD& offset,xVertexElementDatatType Type,\
		xVertexElementMethodType Method,xVertexElementUsageType Usage,	BYTE UsageIndex)
	{
		
		  AddVertexElement(xVertexElement(Stream,offset,Type,Method,Usage,UsageIndex));
		  offset+=GetElementDatatSize(Type);
		  return true;

	}




	bool xVertexDeclaration::AddVertexElement( const xVertexElement& element)
	{
		m_ElementVector.push_back(element);
		return true;
	}


	UINT xVertexDeclaration::GetVertexSize(UINT streamIndex) const
	{
		size_t size = m_ElementVector.size();
		if(size==0)
			return 0;
		UINT  count = 0;
		for(size_t i =0;i<size;++i)
		{
			if(m_ElementVector[i].m_Stream==streamIndex)
			{
				count+=GetElementDatatSize((xVertexElementDatatType)m_ElementVector[i].m_Datatype);
			}

		}
		return count;

	}

	UINT xVertexDeclaration::GetVertexSize() const 
	{
		size_t size = m_ElementVector.size();
		if(size==0)
			return 0;
		UINT  count = 0;
		for(size_t i =0;i<size;++i)
		{
			count+=GetElementDatatSize((xVertexElementDatatType)m_ElementVector[i].m_Datatype);
		}
		return count;
	}

	void  xVertexDeclaration::Clear()
	{
		m_ElementVector.clear();
		return ;
	}

	//if cont find Element return -1;
	int   xVertexDeclaration::GetElementOffset(xVertexElementUsageType usagetype) const
	{
		size_t size = m_ElementVector.size();
		for(size_t i =0;i<size;++i)
		{
			if(m_ElementVector[i].m_UsageType==usagetype)
				return m_ElementVector[i].m_Offset;
		}
		return -1;
	}

	bool  xVertexDeclaration::HasElementUsageType(xVertexElementUsageType usagetype) const
	{
		size_t size = m_ElementVector.size();
		for(size_t i =0;i<size;++i)
		{
			if(m_ElementVector[i].m_UsageType==usagetype)
				return true;
		}
		return false;
	}


	bool xVertexDeclaration::AddEndElement()
	{
		m_ElementVector.push_back(xVertexElement((WORD)0xFF,(WORD)0,D3DDECLTYPE_UNUSED, (xVertexElementMethodType)0,(xVertexElementUsageType)0,(BYTE)0) );
	    return true;;

	}

	
	WORD xVertexDeclaration::GetElementDatatSize(xVertexElementDatatType datatype) const
	{

		switch ( datatype)
		{

		case   D3DDECLTYPE_FLOAT1:
			{
				return 4;
			}// 1D float expanded to (value, 0., 0., 1.)
		case	D3DDECLTYPE_FLOAT2  ://=  1,  // 2D float expanded to (value, value, 0., 1.)
			{
				return 8;

			}
		case	D3DDECLTYPE_FLOAT3   :// =  2,  // 3D float expanded to (value, value, value, 1.)
			{
				return 12;
			}
		case	D3DDECLTYPE_FLOAT4   :// =  3,  // 4D float
			{
				return 16;
			}
		case	D3DDECLTYPE_D3DCOLOR :// =  4,  // 4D packed unsigned bytes mapped to 0. to 1. range
			{
				return 4;
			}
			// Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
		case	D3DDECLTYPE_UBYTE4 ://   =  5,  // 4D unsigned byte
			{
				return 4;

			}
		case	D3DDECLTYPE_SHORT2 ://   =  6,  // 2D signed short expanded to (value, value, 0., 1.)
			{
				return 2;
			}
		case	D3DDECLTYPE_SHORT4 ://   =  7,  // 4D signed short
			{
				return 4;

			}
			// The following types are valid only with vertex shaders >= 2.0
		case	D3DDECLTYPE_UBYTE4N ://  =  8,  // Each of 4 bytes is normalized by dividing to 255.0
			{
				return 4;
			}
		case	D3DDECLTYPE_SHORT2N://   =  9,  // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
			{
				return 2;
			}
		case	D3DDECLTYPE_SHORT4N ://  = 10,  // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
			{
				return 4;
			}
		case	D3DDECLTYPE_USHORT2N :// = 11,  // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
			{
				return 2;
			}
		case	D3DDECLTYPE_USHORT4N :// = 12,  // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
			{
				return 4;
			}
		case	D3DDECLTYPE_UDEC3:// = 13,  // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
			{
				return 3;
			}
		case	D3DDECLTYPE_DEC3N ://    = 14,  // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
			{
				return 3;
			}
		case	D3DDECLTYPE_FLOAT16_2:// = 15,  // Two 16-bit floating point values, expanded to (value, value, 0, 1)
			{
				return 32;
			}
		case	D3DDECLTYPE_FLOAT16_4:// = 16,  // Four 16-bit floating point values
			{
				return 16*4;
			}
		case  D3DDECLTYPE_UNUSED:
			{
				return 0;
			}
		default:
			{
				xLogMessager::getSingleton().logMessage("cont find vertexElement datas size");
				return 0;
			}
		}

		return 0;
	}



	bool operator ==(const xVertexDeclaration&d0,const xVertexDeclaration&d1 )
	{
		return true;
	}
	bool operator <(const xVertexDeclaration&d0,const xVertexDeclaration&d1 )
	{
		return true;
	}




}